import org.eclipse.swt.events.PaintEvent;

public class SmartRobot extends AbstractRobotDecorator{

	private int destDeg = 0;
	int speedLimit;
	int headingLimit;
	
	public enum Direction{RIGHT, LEFT}
	Direction direction;
	
	//constructor receives robot
	SmartRobot(Robot r){
		super(r);
		speedLimit = robot.getSpeedLimit();
		headingLimit = robot.getHeadingLimit();
	}
		
	//move robot = set its speed and direction according to limits
	 public void move(int speed, int degree) {
		 //set speed
		 if(Math.abs(speed) <= speedLimit)
			 robot.setSpeed(speed);
		 else if( speed < 0)
			 robot.setSpeed(speedLimit * -1);
		 else
			 robot.setSpeed(speedLimit);
		 //set heading direction - headTo is a degree between 0 and 359
		 destDeg = setDirection(degree);
		 
		 int heading = robot.getHeading();
		 
		 //if destination degree is in limit set heading to it
		 if((direction == Direction.RIGHT && realMod((destDeg - heading), 360) <= headingLimit)
			 || (direction == Direction.LEFT && realMod((heading - destDeg), 360) <= headingLimit))
			 	robot.setHeading(destDeg);
	 }
			
	 //method sets heading degree according to heading limit and destination degree
	 private void setHeading(){
		 int currHeading = robot.getHeading();
		 //check if can move to destination direction
		 if(Math.abs(currHeading - destDeg) <= headingLimit)
			 robot.setHeading(destDeg);
		 //if can't - move as much as possible
		 else if( direction == Direction.LEFT)
			 robot.setHeading(realMod(currHeading -= headingLimit, 360));
		 else
			 robot.setHeading((currHeading + headingLimit) % 360);
	 }
	 
	 //act method - sets robot's current position to new position according to heading and speed
	 public void act() {
		 //if not heading in degree of destination then change heading
		 if( robot.getHeading() != destDeg)
			 setHeading();
		robot.act();
	 }
	
	//function receives heading angle and decides in which direction to move
	private int setDirection(int deg){
		// set degree to positive smaller than 360
		deg = realMod(deg,360);
		
		int heading = robot.getHeading();
		int moveRight = realMod((deg - heading) , 360);
		int moveLeft = realMod((heading - deg)  , 360); 
		
		//set direction according to smaller amount
		if(moveLeft < moveRight)
			direction = Direction.LEFT;
		else
			direction = Direction.RIGHT;
		
		return deg;
	}
	
	//function computes num % mod returning a number between 0 and mod
	private int realMod(int num, int mod){
		num = num % mod;
		if ( num < 0 )
			num += mod;
		return num;
	}

	public boolean pickupBox(Box box) {return robot.pickupBox(box); }
	//returns true if put down box and false if didn't
	public boolean putdownBox() { return robot.putdownBox(); }	
	
	
	//paints robot to canvas
	public void paint(PaintEvent e){robot.paint(e);}
}
	
	
	


